﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using Spring.Data.Generic;
using Spring.Objects.Factory.Xml;
using Spring.Context.Support;
using Spring.Transaction;
using Spring.Transaction.Support;
using System.Reflection;
using Spring.Data;
using Spring.Data.Common;
using System.Data;


namespace WeiXinWeb.Helper
{
    public static class DBHelper {
        private static AdoTemplate adoTemplate;

        private static TransactionTemplate transactionTemplate;

        public static AdoTemplate AdoTemplate {
            get {
                if (adoTemplate == null) {
                    var ctx = ContextRegistry.GetContext();
                    adoTemplate = ctx["adoTemplate"] as AdoTemplate;
                }

                return adoTemplate;
            }
        }

        public static TransactionTemplate TransactionTemplate {
            get {
                if (transactionTemplate == null) {
                    var ctx = ContextRegistry.GetContext();
                    var tm = ctx["TransactionManager"] as IPlatformTransactionManager;

                    transactionTemplate = new TransactionTemplate(tm) {
                        TransactionIsolationLevel = System.Data.IsolationLevel.Serializable,
                        TransactionTimeout = 300
                    };
                }

                return transactionTemplate;
            }
        }

        ///// <summary>
        ///// log4net
        ///// </summary>
        //public static ILog Logger {
        //    get {
        //        return LogManager.GetLogger("PSI");
        //    }
        //}
    }

    public delegate T QueryObjectDelegate<T>(IDataReader dataReader);

    public static class AdoTemplateExt {
        /// <summary>
        /// 执行insert、delete、update等SQL语句
        /// </summary>
        /// <param name="db"></param>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static int Execute(this AdoTemplate db, string sql, IDbParameters parameters) {
            return db.ExecuteNonQuery(System.Data.CommandType.Text, sql, parameters);
        }
        
        public static int Execute(this AdoTemplate db, string sql) {
            return db.ExecuteNonQuery(System.Data.CommandType.Text, sql);
        }

        public static void Query(this AdoTemplate db, string sql,
            RowCallbackDelegate rowCallbackDelegate) {
            db.QueryWithRowCallbackDelegate(CommandType.Text, sql, rowCallbackDelegate);
        }

        public static void Query(this AdoTemplate db, string sql,
            RowCallbackDelegate rowCallbackDelegate, IDbParameters parameters) {
            db.QueryWithRowCallbackDelegate(CommandType.Text, sql, rowCallbackDelegate, parameters);
        }

        public static T QueryObject<T>(this AdoTemplate db, string sql,
            QueryObjectDelegate<T> rowCallbackDelegate, IDbParameters parameters) {
            return db.QueryForObjectDelegate<T>(CommandType.Text, sql,
                (reader, num) => {
                    return rowCallbackDelegate(reader);
                }, parameters);
        }

        /// <summary>
        /// 执行类似 select count(*) from ... 的语句，返回结果值
        /// </summary>
        /// <param name="db"></param>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static int QueryCount(this AdoTemplate db, string sql, IDbParameters parameters) {
            return db.QueryForObjectDelegate<int>(CommandType.Text, sql,
                (reader, num) => {
                    return reader.GetInt32(0);
                }, parameters);
        }
    }


    public delegate void TransactionDelegateEx();

    public static class TransactionTemplateExt {
        public static void WithTransaction(this TransactionTemplate tx, TransactionDelegateEx td) {
            tx.Execute(status => {
                td();

                return null;
            });
        }
    }
}